package com.fingerUsb;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.Toast;

import com.techshinogongjian.fingerprint.TCFP;
import com.techshinogongjian.fp.client.TcFingerClient;
import com.techshinogongjian.fp.comm.HIDComm;
import com.techshinogongjian.fp.comm.SimpleComm;
import com.techshinogongjian.fp.comm.TwoUsbComm;
import com.techshinogongjian.fp.func.HIDFuncImpl;
import com.techshinogongjian.fp.func.IFingerprintFunc;
import com.techshinogongjian.fp.func.SimpleFuncImpl;
import com.techshinogongjian.fp.func.TwoUsbFuncImpl;
import com.techshinogongjian.fp.util.Logs;
import com.techshinogongjian.fp.util.USBUtil;
import com.wellcom.finger.FpDriverV22;

import org.zz.protocol.MXCommand;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;

/**
 * usb指纹工具类
 * 维尔，中正，天诚都在这里
 *
 * @author zouhuaqiu
 */
public class USBComm {


    private static final String TAG = "USBComm";
    private static final String ACTION_USB_PERMISSION = "com.siecom.ghkj.ACTION_USB";


    private USBUtil.Protocol mProtocol = USBUtil.Protocol.SIMPLE;
    public static final int VENDOR_ID0 = 29535; // 这里要改成自己的硬件ID
    public static final int PRODUCT_ID0 = 4865;
    public static final int VENDOR_ID1 = 29535; // 这里要改成自己的硬件ID
    public static final int PRODUCT_ID1 = 4867;
    public static final int VENDOR_ID2 = 29535; // 这里要改成自己的硬件ID
    public static final int PRODUCT_ID2 = 61185;
    public static final int HID_VENDOR_ID = 29535;
    public static final int HID_PRODUCT_ID = 4866;

    private static USBComm mInstance;

    private Context mContext;
    private UsbManager mUsbManager;
    private UsbDevice mUsbDevice;
    private UsbInterface mInterface;
    private UsbDeviceConnection mDeviceConnection;
    private int mVendorId;
    private int mProductId;
    private UsbEndpoint mEpOut;
    private UsbEndpoint mEpIn;
    private TcFingerClient mClient;
    private IFingerprintFunc mFingerprintFunc;
    private OnConnectListener mConnectListener;
    private TCFP mTcfp;
    private boolean isRegisterMonitor = false;
    private boolean isConnecting = false;
    private boolean isClosing = false;

    /**
     * wellcom的
     */
    private static int isLoadOK = FpDriverV22.isLoadOK;
    private static int isRoot;
    private static String sLoadErrMsg;
    private static final int IMAGE_LEN_BASE64 = ((152 * 200 + 1078) * 4 / 3 + 3);
    private static final int WELL_VID = 0x2796;
    private static final int WELL_PID1 = 0x0998;
    private static final int WELL_PID2 = 0x8195;
    private int fd = 0;
    private String devNode;


    private int m_iSendPackageSize = 0;
    private int m_iRecvPackageSize = 0;
    private UsbDevice m_usbDevice = null;
    private UsbInterface m_usbInterface = null;
    private UsbEndpoint m_inEndpoint = null;
    private UsbEndpoint m_outEndpoint = null;
    private UsbDeviceConnection m_connection = null;
    private Context m_ctx = null;
    private Handler m_fHandler = null;

    public static volatile int TYPE = 0;//1.天成，2.中正 3.维尔

    private USBComm(@NonNull Context context) {
        mContext = context;
        mUsbManager = (UsbManager) mContext
                .getSystemService(Context.USB_SERVICE);

        this.m_ctx = context;
        this.m_fHandler = null;

        registerMonitor();
    }

    public static USBComm getInstance(@NonNull Context context) {
        if (mInstance == null) {
            mInstance = new USBComm(context);
        }
        return mInstance;
    }

    public void setProtocol(USBUtil.Protocol protocol) {
        mProtocol = protocol;
    }

    public void setConnectListener(OnConnectListener connectListener) {
        mConnectListener = connectListener;
    }

    private void registerMonitor() {
        isRegisterMonitor = true;
        // 注册USB设备权限管理广播
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
        mContext.registerReceiver(usbReceiver, filter);
    }

    public void unRegisterMonitor() {
        if (isRegisterMonitor) {
            mContext.unregisterReceiver(usbReceiver);
        }
    }

    /**
     * 连接设备
     */
    public void connectDevice() {
        Logs.i(TAG, "connectDevice...");

        if (checkDeviceState()) {
            Logs.e(TAG, "1已连接");
            return;
        }
        if (mClient != null && mClient.isConnected()) {
            Logs.e(TAG, "2已连接");
            connected();
            return;
        }
        if (TYPE == 3 && fd > 0) {
            Logs.e(TAG, "3已连接");
            connected();
            return;

        }

        isConnecting = true;

        registerMonitor();

        enumerateDevice();

        isConnecting = false;
    }

    /**
     * 断开设备
     */
    public void disconnectDevice() {

        isClosing = true;
        if (mDeviceConnection != null) {
            if (TYPE == 1) {
                mClient.tcCancel();
                if (mProtocol != USBUtil.Protocol.HID) {
                    mDeviceConnection.releaseInterface(mInterface);
                }
                mDeviceConnection.close();
                mDeviceConnection = null;
                mClient = null;
                mFingerprintFunc = null;
                unRegisterMonitor();
            }
        }
        if (mTcfp != null) {
            mTcfp.TCFP_UnInit();
            mTcfp = null;
        }
        if (TYPE == 3) {

            FpDriverV22.FPIDeviceClose();

        }


        isClosing = false;
        Logs.i(TAG, "disconnectDevice...");
    }

    private boolean checkDeviceState() {
        if (isConnecting || isClosing || (mClient != null && mClient.isBusy())) {
            connectFailed("设备忙");
            return true;
        }
        return false;
    }

    /**
     * 枚举设备
     */
    private synchronized void enumerateDevice() {
        Log.e(TAG, "enumerateDevice");
        TYPE = 0;
        fd = 0;
        mUsbManager = (UsbManager) mContext
                .getSystemService(Context.USB_SERVICE);

        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();

        if (!deviceList.isEmpty()) { // deviceList不为空
            StringBuffer sb = new StringBuffer();
            for (UsbDevice device : deviceList.values()) {
                sb.append(device.toString());
                sb.append("\n");
                // info.setText(sb);
                // 输出设备信息
                Logs.e(TAG, "DeviceInfo: " + device.getVendorId() + " , "
                        + device.getProductId());
                // 枚举到设备
                if (device.getVendorId() == VENDOR_ID0) {
                    TYPE = 1;
                    openDevice(device);
                    Log.e(TAG, "枚举天成成功");

                }

                if (device.getVendorId() == MXCommand.VENDORID) {
                    TYPE = 2;
                    Log.e(TAG, "枚举中正成功");
                    openDev(device);

                }
                if ((device.getVendorId() == WELL_VID) && (device.getProductId() == WELL_PID1 || device.getProductId() == WELL_PID2)) {

                    Log.e(TAG, "枚举维尔成功");
                    openWellDev(device);

                }


            }
        }
    }

    private void openWellDev(UsbDevice device) {
        if (this.m_ctx == null) {
            Log.e(TAG, "ERRCODE_NO_CONTEXT");
        } else {

            if (!mUsbManager.hasPermission(device)) {
                Log.e(TAG, "wellName: " + device.getDeviceName());
                PendingIntent pi = PendingIntent.getBroadcast(this.m_ctx, 0, new Intent(ACTION_USB_PERMISSION), 0);
                mUsbManager.requestPermission(device, pi);
                return;
            }
            if (TYPE == 3 && fd > 0) {

                connected();
                return;
            }

            Log.e(TAG, "wellvid: " + device.getVendorId() + "\t pid: " + device.getProductId());
            devNode = device.getDeviceName();
            mDeviceConnection = mUsbManager.openDevice(device);

            if (mDeviceConnection != null) {
                fd = mDeviceConnection.getFileDescriptor();
                Log.e(TAG, "--->getFileDescriptor:" + String.valueOf(fd));
                Log.e(TAG, "FindAndOpenFpDev End");
                if (fd > 0) {


                    int iRet = FpDriverV22.FPIDeviceInit(fd, devNode);

                    Log.e(TAG, "FPIDeviceInit:" + iRet);
                    TYPE = 3;

                    connected();


                } else {
                    connectFailed("open well fail");
                }

            }


        }

    }

    /*
 * 关闭设备
 */
    private void FPICloseFpDev() {
        Log.i(TAG, "FPICloseFpDev");
        if (mDeviceConnection != null) {
            mDeviceConnection.close();
            mDeviceConnection = null;
        }

    }

    /**
     * 打开串口电源
     *
     * @return
     */
    public String[] power_on() {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            int iRet = -1;

            iRet = FpDriverV22.FPIPowerOn();
            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);
            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }

    }

    /**
     * 打关闭串口电源
     *
     * @return
     */
    public String[] power_off() {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            int iRet = -1;

            iRet = FpDriverV22.FPIPowerOff();

            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);
            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }

    }

    /**
     * @return
     */
    public String[] openDeviceRS232(String path_utf, int baudrate, int flags) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {

            Log.i(TAG, "openDeviceRS232");

            File device = new File(path_utf);
            /* Check access permission */
            if (!device.canRead() || !device.canWrite()) {
                try {

					/* Missing read/write permission, trying to chmod the file */
                    Process su;
                    su = Runtime.getRuntime().exec("/system/bin/su");
                    String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" + "exit\n";
                    su.getOutputStream().write(cmd.getBytes());
                    if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {

                        throw new SecurityException();
                    }


                } catch (Exception e) {

                    e.printStackTrace();
                    throw new SecurityException();
                }
            }

            int iRet = -1;
            iRet = FpDriverV22.FPIDeviceInitRS232(device.getAbsolutePath().getBytes(), baudrate, flags);
            Log.i(TAG, "FPIDeviceInit = " + iRet);
            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);
            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }

    }


    /**
     * 指纹模板登记
     *
     * @return
     */
    public String[] getFpVersion() {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            byte[] psDevInfo = new byte[100];
            int iRet = -1;

            iRet = FpDriverV22.FPIGetVersion(psDevInfo);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);
                return arrRet;
            }

            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psDevInfo).trim();

            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }

    /**
     * 获取设备序列号
     *
     * @return
     */
    public String[] getDeviceID() {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {

            byte[] psDeviceID = new byte[60];
            int iRet = -1;

            iRet = FpDriverV22.FPIGetDeviceID(psDeviceID);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }


            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psDeviceID);
            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }

    /**
     * 指纹模板登记
     *
     * @return
     */
    public String[] registerFinger(int nTimeout) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;
            return arrRet;
        }
        try {
            byte[] psTemplateBuf = new byte[1024];
            int[] pnLength = new int[2];
            int iRet = -1;

            iRet = FpDriverV22.FPIGetTemplate(nTimeout, psTemplateBuf, pnLength);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }

            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psTemplateBuf).trim();

            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }

    }

    /**
     * 读取指纹特征
     *
     * @return
     */
    public String[] readFinger(int nTimeout) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            byte[] psFeatureBuf = new byte[1024];
            int[] pnLength = new int[2];
            int iRet = -1;

            iRet = FpDriverV22.FPIGetFeature(nTimeout, psFeatureBuf, pnLength);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);
                return arrRet;
            }

            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psFeatureBuf).trim();

            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }


    /**
     * 异步采集后进行合成
     *
     * @return
     */
    public String[] checkFinger() {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {

            int iRet = -1;
            iRet = FpDriverV22.FPICheckFinger();
            if (iRet < 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }

            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            if (iRet == 0) {
                arrRet[1] = "finger is down";
            } else {
                arrRet[1] = "finger is up";
            }

            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }

    /**
     * 异步采集后进行合成
     *
     * @return
     */
    public String[] getImage(int nTimeOut, String sBmpFile) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            byte[] psImage = new byte[IMAGE_LEN_BASE64];
            int[] pnLength = new int[2];
            byte[] psMAC = new byte[20];
            int[] iIsValid = new int[2];
            byte[] psBmpFile = sBmpFile.getBytes();

            int iRet = -1;
            iRet = FpDriverV22.FPIGetImage(nTimeOut, psImage, pnLength, psBmpFile);
            if (iRet < 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);
                return arrRet;
            }

            String[] arrRet = new String[4];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psImage);
            arrRet[2] = Integer.toString(pnLength[0]);
            arrRet[3] = Integer.toString(iIsValid[0]);

            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }


    /**
     * 获取指纹图像，并解析图像格式
     *
     * @return
     */
    public String[] getImageEx(int nTimeOut, String sBmpFile) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            byte[] psImage = new byte[IMAGE_LEN_BASE64];
            int[] pnLength = new int[2];
            byte[] psMAC = new byte[20];
            int[] iIsValid = new int[2];
            int[] iQuility = new int[2];
            byte[] psBmpFile = sBmpFile.getBytes();

            int iRet = -1;
            iRet = FpDriverV22.FPIGetImageEx(nTimeOut, psImage, pnLength, iIsValid, iQuility, psBmpFile);
            if (iRet < 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }

            String[] arrRet = new String[6];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psImage);
            arrRet[2] = Integer.toString(pnLength[0]);
            arrRet[3] = new String(psMAC);
            arrRet[4] = Integer.toString(iIsValid[0]);
            arrRet[5] = Integer.toString(iQuility[0]);

            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }

    /**
     * 取消操作
     *
     * @return
     */
    public String[] cancel() {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {

            FpDriverV22.FPICancel();

            String[] arrRet = new String[2];
            arrRet[0] = "0";
            arrRet[1] = "success";

            return arrRet;

        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }


    public String[] getFeatureByImg(byte[] psImage) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            int iRet = -1;
            byte[] psVerBuf = new byte[1024];
            int[] pnLength = new int[2];

            iRet = FpDriverV22.FPIGetFeatureByImg(psImage, psVerBuf, pnLength);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }

            String[] arrRet = new String[3];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psVerBuf).trim();
            arrRet[2] = Integer.toString(pnLength[0]);

            return arrRet;

        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }


    }

    public String[] getTemplateByImg(String sImage1, String sImage2, String sImage3) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            int iRet = -1;
            byte[] psRegBuf = new byte[1024];
            int[] pnLength = new int[2];

            iRet = FpDriverV22.FPIGetTemplateByImg(sImage1.getBytes(), sImage2.getBytes(), sImage3.getBytes(), psRegBuf, pnLength);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }

            String[] arrRet = new String[3];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psRegBuf).trim();
            arrRet[2] = Integer.toString(pnLength[0]);

            return arrRet;

        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }

    }

    public String[] fpVerify(String sMB, String sTZ, int nLevel) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            int iRet = -1;
            byte[] psRegBuf = new byte[1024];
            int[] pnLength = new int[2];

            iRet = FpDriverV22.FPIFpVerify(sMB.getBytes(), sTZ.getBytes(), nLevel);
            String[] arrRet = new String[2];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

            return arrRet;

        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }

    }

    public String[] getTemplateByTZ(String sTZ1, String sTZ2, String sTZ3) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            int iRet = -1;
            byte[] psRegBuf = new byte[1024];
            int[] pnLength = new int[2];

            iRet = FpDriverV22.FPIEnrollX(sTZ1.getBytes(), sTZ2.getBytes(), sTZ3.getBytes(), psRegBuf, pnLength);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }

            String[] arrRet = new String[3];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psRegBuf).trim();
            arrRet[2] = Integer.toString(pnLength[0]);

            return arrRet;

        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }

    }

    /**
     * 读取指纹特征，并上传指纹图像
     *
     * @return
     */
    public String[] readFingerAndImage(int nTimeout, String sBmpFile) {

        if (isLoadOK != 0) {
            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = sLoadErrMsg;

            return arrRet;
        }

        try {
            byte[] psFeatureBuf = new byte[1024];
            int[] pnFeatureLen = new int[2];
            byte[] psImage = new byte[IMAGE_LEN_BASE64];
            int[] pnImageLen = new int[2];
            int[] iIsValid = new int[2];
            byte[] psBmpFile = sBmpFile.getBytes();
            int iRet = -1;

            iRet = FpDriverV22.FPIGetFeatureAndImage(nTimeout, psFeatureBuf, pnFeatureLen, psImage, pnImageLen, psBmpFile);
            if (iRet != 0) {
                String[] arrRet = new String[2];
                arrRet[0] = Integer.toString(iRet);
                arrRet[1] = FpDriverV22.FPIGetErrorInfo(iRet);

                return arrRet;
            }

            String[] arrRet = new String[5];
            arrRet[0] = Integer.toString(iRet);
            arrRet[1] = new String(psFeatureBuf).trim();
            arrRet[2] = new String(psImage).trim();
            arrRet[3] = Integer.toString(pnImageLen[0]);
            arrRet[4] = Integer.toString(iIsValid[0]);

            return arrRet;
        } catch (Throwable ex) {

            //IFpDevDriver.logger.error(ex.toString());

            String[] arrRet = new String[2];
            arrRet[0] = "-101";
            arrRet[1] = ex.toString();

            return arrRet;
        }
    }


    /**
     * 找设备接口
     */
    private void findInterface() {
        if (mUsbDevice != null) {
            Logs.d(TAG, "interfaceCounts : " + mUsbDevice.getInterfaceCount());
            for (int i = 0; i < mUsbDevice.getInterfaceCount(); i++) {
                UsbInterface intf = mUsbDevice.getInterface(i);
                if (i == 0) {
                    mInterface = intf; // 保存设备接口
                    Logs.d(TAG, "找到我的设备接口：" + mInterface.getId());
                }
            }
        } else {
            connectFailed("未找到设备");
        }
    }

    /**
     * 分配端点，IN | OUT，即输入输出；此处我直接用1为OUT端点，0为IN，当然你也可以通过判断
     */
    // USB_ENDPOINT_XFER_BULK
    /*
     * #define USB_ENDPOINT_XFER_CONTROL 0 --控制传输 #define USB_ENDPOINT_XFER_ISOC
	 * 1 --等时传输 #define USB_ENDPOINT_XFER_BULK 2 --块传输 #define 3
	 * --中断传输#USB_ENDPOINT_XFER_INT
	 */
    private void assignEndpoint() {
        if (mInterface != null) { // 这一句不加的话 很容易报错 导致很多人在各大论坛问:为什么报错呀
            // 这里的代码替换了一下 按自己硬件属性判断吧
            for (int i = 0; i < mInterface.getEndpointCount(); i++) {
                UsbEndpoint ep = mInterface.getEndpoint(i);
                Logs.i(TAG, "type:" + ep.getType());
                Logs.i(TAG, "direction:" + ep.getDirection());
                if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                    // setProtocol(Protocol.SIMPLE);
                    if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                        mEpOut = ep;
                    } else {
                        mEpIn = ep;
                    }
                }
                if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
                    setProtocol(USBUtil.Protocol.HID);
                    if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                        mEpOut = ep;
                    } else {
                        mEpIn = ep;
                    }
                }
            }
        }
    }


    /**
     * 打开设备
     */
    private synchronized void openDevice(UsbDevice mUsbDevice) {


        UsbDeviceConnection conn = null;
        // 在open前判断是否有连接权限；对于连接权限可以静态分配，也可以动态分配权限，可以查阅相关资料
        Log.e("openDevice", "openDevice====");
        if (mUsbManager.hasPermission(mUsbDevice)) {
            this.mUsbDevice = mUsbDevice;
            conn = mUsbManager.openDevice(mUsbDevice);
            findInterface();
            assignEndpoint();
            if (conn == null) {
                Log.e(TAG, "打开设备失败");
                connectFailed("打开设备失败");
                return;
            }
            if (conn.claimInterface(mInterface, true)) {
                mDeviceConnection = conn; // 到此你的android设备已经连上HID设备
                Log.e(TAG, "打开设备成功");
                if (mEpIn == null || mEpOut == null) {

                    connectFailed("找不到设备节点");
                    return;
                }
                //Log.e("test","1");
                if (mProtocol == USBUtil.Protocol.SIMPLE) {
                    Logs.i(TAG, "simple...");
                    // FPConfig.setFeatureType(FPConfig.FEATURE_TYPE_V500_GA);
                    //  Log.e("test","2");
                    SimpleComm comm = new SimpleComm(mDeviceConnection, mEpIn,
                            mEpOut);
                    comm.setPid(mUsbDevice.getProductId());
                    mFingerprintFunc = new SimpleFuncImpl(comm);
                    mClient = new TcFingerClient(mFingerprintFunc, mContext);
                    comm.setInitOk(initTCFP());
                } else if (mProtocol == USBUtil.Protocol.TWO) {
                    Logs.i(TAG, "two...");
                    // Log.e("test","3");

                    mFingerprintFunc = new TwoUsbFuncImpl(new TwoUsbComm(
                            mDeviceConnection, mEpIn, mEpOut));

                    mClient = new TcFingerClient(mFingerprintFunc, mContext);
                } else {
                    Logs.i(TAG, "hid...");
                    Log.e("test", "4");
//					FPConfig.setFeatureType(FPConfig.FEATURE_TYPE_BASE64);
                    HIDComm comm = new HIDComm(mDeviceConnection, mEpIn, mEpOut);
                    mFingerprintFunc = new HIDFuncImpl(comm);
                    mClient = new TcFingerClient(mFingerprintFunc, mContext);

                    comm.setInitOk(initTCFP());
                }
                //   Log.e("test","5");
                connected();
            } else {
                Log.e("open fail", "~~~~");
                conn.close();
                return;
            }
        } else {
            PendingIntent intent = PendingIntent.getBroadcast(mContext, 0,
                    new Intent(ACTION_USB_PERMISSION), 0);
            mUsbManager.requestPermission(mUsbDevice, intent);
        }


    }

    /**
     * 初始化算法
     */
    private boolean initTCFP() {
        String path = Environment.getExternalStorageDirectory().getPath()
                + "/TcFingerprintTemp";
        File file = new File(path);
        if (!file.exists() || file.isFile()) {
            file.mkdir();
        }
        // 初始化指纹算法
        int fd = mDeviceConnection.getFileDescriptor();
        if (mTcfp != null) {
            mTcfp.TCFP_UnInit();
            mTcfp = null;
        }
        mTcfp = new TCFP(mContext);
        int code = mTcfp.TCFP_Init(1, fd, path);
        return code == 1;
    }


    private void connected() {
        Log.e("connected", "here");
        if (mConnectListener != null) {
            mConnectListener.onConnected(TYPE, mClient, this);
        }
    }


    private void connectFailed(String msg) {
        if (mConnectListener != null) {
            mConnectListener.onConnectFailed(-1, msg);
        }
    }


    private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {

        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {

                Log.e("DEVICE_ATTACHED", "---");

                connectDevice();


            }

            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = (UsbDevice) intent
                            .getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(
                            UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (device != null) {
                            if (device.getVendorId() == VENDOR_ID0) {
                                openDevice(device);

                            }
                            if (device.getVendorId() == MXCommand.VENDORID) {
                                openDev(device);

                            }
                            if (device.getVendorId() == WELL_VID) {

                                openWellDev(device);
                            }
                        }
                    } else {
                        connectFailed("用户拒绝访问");
                    }
                }
            }
            if ("android.hardware.usb.action.USB_DEVICE_DETACHED".equals(action)) {
                UsbDevice device = (UsbDevice) intent.getParcelableExtra("device");
                if (device != null && device.getVendorId() == MXCommand.VENDORID) {
                    if (m_connection != null) {
                        m_connection.releaseInterface(m_usbInterface);
                        m_connection.close();
                    }
                }
                if (device != null && device.getVendorId() == WELL_VID) {

                    FpDriverV22.FPIDeviceClose();
                    TYPE = 0;
                    fd = 0;
                }
            }
        }
    };


    public String getDevAttribute() {
        if (this.m_ctx == null) {
            return null;
        } else {
            int iDevNum = 0;
            String strDevInfo = "";
            String strTmp = null;
            UsbManager usbManager = (UsbManager) this.m_ctx.getSystemService(Context.USB_SERVICE);
            HashMap map = usbManager.getDeviceList();
            Iterator var7 = map.values().iterator();

            while (var7.hasNext()) {
                UsbDevice device = (UsbDevice) var7.next();
                if (!usbManager.hasPermission(device)) {
                    PendingIntent pi = PendingIntent.getBroadcast(this.m_ctx, 0, new Intent(ACTION_USB_PERMISSION), 0);
                    usbManager.requestPermission(device, pi);
                    return null;
                }

                ++iDevNum;
                strTmp = "DescribeContents:" + device.describeContents();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "DeviceProtocol:" + device.getDeviceProtocol();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "DeviceClass:" + device.getDeviceClass();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "DeviceSubclass:" + device.getDeviceSubclass();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "InterfaceCount:" + device.getInterfaceCount();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "DeviceId:" + device.getDeviceId();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "DeviceName:" + device.getDeviceName();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "VendorId:" + device.getVendorId();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                strTmp = "ProductId:" + device.getProductId();
                strDevInfo = strDevInfo + strTmp + "\r\n";
                Log.e(TAG, "Device\r\n" + strDevInfo);
            }

            return strDevInfo;
        }
    }

    public int getDevNum(int vid, int pid) {
        if (this.m_ctx == null) {
            return -102;
        } else {
            int iDevNum = 0;
            UsbManager usbManager = (UsbManager) this.m_ctx.getSystemService(Context.USB_SERVICE);
            HashMap map = usbManager.getDeviceList();
            Iterator var7 = map.values().iterator();

            while (var7.hasNext()) {
                UsbDevice device = (UsbDevice) var7.next();
                if (!usbManager.hasPermission(device)) {
                    PendingIntent pi = PendingIntent.getBroadcast(this.m_ctx, 0, new Intent(ACTION_USB_PERMISSION), 0);
                    usbManager.requestPermission(device, pi);
                    return -101;
                }

                if (vid == device.getVendorId() && pid == device.getProductId()) {
                    ++iDevNum;
                }
            }

            return iDevNum;
        }
    }

    public int openDev(UsbDevice device) {
        Log.e(TAG, "openDev");

        if (this.m_ctx == null) {
            Log.e(TAG, "ERRCODE_NO_CONTEXT");
            return -102;
        } else {

            if (!mUsbManager.hasPermission(device)) {
                Log.e(TAG, "dName: " + device.getDeviceName());
                PendingIntent pi = PendingIntent.getBroadcast(this.m_ctx, 0, new Intent(ACTION_USB_PERMISSION), 0);
                mUsbManager.requestPermission(device, pi);
                return -101;
            }
            Log.e(TAG, "vid: " + device.getVendorId() + "\t pid: " + device.getProductId());

            this.m_usbDevice = device;
            this.m_usbInterface = this.m_usbDevice.getInterface(0);
            this.m_inEndpoint = this.m_usbInterface.getEndpoint(0);
            this.m_outEndpoint = this.m_usbInterface.getEndpoint(1);
            this.m_connection = mUsbManager.openDevice(this.m_usbDevice);
            this.m_connection.claimInterface(this.m_usbInterface, true);
            this.m_iSendPackageSize = this.m_outEndpoint.getMaxPacketSize();
            this.m_iRecvPackageSize = this.m_inEndpoint.getMaxPacketSize();
            Log.e(TAG, "-------------------------------------------");
            Log.e(TAG, "SendPackageSize: " + this.m_iSendPackageSize + ",RecvPackageSize: " + this.m_iRecvPackageSize);
            connected();
            return 0;

        }
    }

    public int sendPacketSize() {
        return this.m_iSendPackageSize;
    }

    public int recvPacketSize() {
        return this.m_iRecvPackageSize;
    }

    public int clearBuffer() {
        if (this.m_connection == null) {

            return -10;
        }
        boolean iRV = false;
        int iEndpointSize = this.recvPacketSize();
        byte[] bRecvBufTmp = new byte[iEndpointSize];

        while (true) {
            int iRV1 = this.m_connection.bulkTransfer(this.m_inEndpoint, bRecvBufTmp, iEndpointSize, 5);
            if (iRV1 < 0) {
                return 0;
            }

            Log.e(TAG, "clearBuffer iRV=" + iRV1);
        }
    }

    public int sendData(byte[] bSendBuf, int iSendLen, int iTimeOut) {
        if (this.m_connection == null) {

            return -10;
        }
        boolean iRV = true;
        if (iSendLen > bSendBuf.length) {
            return -18;
        } else {
            int iPackageSize = this.sendPacketSize();
            if (iSendLen > iPackageSize) {
                return -18;
            } else {
                byte[] bSendBufTmp = new byte[iPackageSize];
                System.arraycopy(bSendBuf, 0, bSendBufTmp, 0, iSendLen);
                int iRV1 = this.m_connection.bulkTransfer(this.m_outEndpoint, bSendBufTmp, iPackageSize, iTimeOut);
                return iRV1;
            }
        }
    }

    public int receiveBytes(byte[] buf, int len, int timeout) {

        return this.m_connection.bulkTransfer(this.m_inEndpoint, buf, len, timeout);
    }

    public int recvData(byte[] bRecvBuf, int iRecvLen, int iTimeOut) {
        if (this.m_connection == null) {

            return -10;
        }
        int iRV = -1;

        if (iRecvLen > bRecvBuf.length) {
            return -18;
        } else {
            int iPackageSize = this.recvPacketSize();
            byte[] bRecvBufTmp = new byte[iPackageSize];

            for (int i = 0; i < iRecvLen; i += iPackageSize) {

                int nDataLen = iRecvLen - i;
                if (nDataLen > iPackageSize) {
                    nDataLen = iPackageSize;
                }
                iRV = this.m_connection.bulkTransfer(this.m_inEndpoint, bRecvBufTmp, nDataLen, iTimeOut);

                if (iRV < 0) {
                    return iRV;
                }
                System.arraycopy(bRecvBufTmp, 0, bRecvBuf, i, iRV);
            }

            return iRV;
        }
    }

    public int closeDev() {
        if (this.m_connection != null) {
            this.m_connection.releaseInterface(this.m_usbInterface);
            this.m_connection.close();
            this.m_connection = null;
        }

        return 0;
    }


    protected void showTmsg(String string) {
        Toast.makeText(mContext, string, Toast.LENGTH_SHORT).show();
    }
}
